/*
 *  DIDDescriptio.cpp
 *  libavid
 *
 *  Created by Peter on 27.02.12.
 *  Copyright 2012 __MyCompanyName__. All rights reserved.
 *
 */

#include "DIDDescriptor.h"
#include "AStream.h"

A_IMPLEMENT_CLASS( 'DIDD', DIDDescriptor, AMediaFileDesc );

static void readAndCheckExtHeader( AStream& str, UInt8 minorVersion, UInt8 tagMark )
{
	UInt8 theTagMark, theMinorVersion;
	str.readPod( theTagMark );
	str.readPod( theMinorVersion );
	TR_ASSERT( theTagMark == 0x01 );
	TR_ASSERT( theMinorVersion == minorVersion );
	str.readPod( theTagMark );
	TR_ASSERT( theTagMark == tagMark );
}

static void readTagMark( AStream& str, UInt8 value )
{
	UInt8 tagMark;
	str.readPod( tagMark );
	TR_ASSERT( tagMark == value );
}

void DIDDescriptor::readFromStream( AStream& str, const AObjDoc& objd )
{
	AMediaFileDesc::readFromStream( str, objd );
	
	UInt8 tagMark, version;
	
	str.readPod( tagMark );
	str.readPod( version );
	
	TR_ASSERT( tagMark == 0x02 );
	TR_ASSERT( version == 0x02 );
	
	str.readPod( _storedHeight );
	str.readPod( _storedWidth );
	str.readPod( _sampledHeight ),
	str.readPod( _sampledWidth );
	str.readPod( _sampledXOffset );
	str.readPod( _sampledYOffset );
	str.readPod( _displayHeight );
	str.readPod( _displayWidth );
	str.readPod( _displayXOffset );
	str.readPod( _displayYOffset );
	str.readPod( _frameLaout );
	_imageAspectRatio.readFromStream( str );
	
	// Video line map
	str.readPod( _videoLineMapSize );
	TR_ASSERT( _videoLineMapSize >= 0 );
	TR_ASSERT( _videoLineMapSize % sizeof( Int32 ) == 0 ); // Number must be in bits ?????
	if( _videoLineMapSize == 0 ) {
		_videoLineMap = nullptr; // FIXME: We could leak something here
	} else {
		_videoLineMap = new Int32[ _videoLineMapSize / sizeof( Int32 ) ];
		for( int i = 0; i < _videoLineMapSize / sizeof( Int32 ); ++i ) {
			str.readPod( _videoLineMap[ i ] );
		}
	}
	
	str.readPod( _alphaTransparency );
	_uniformness = str.readBool();
	str.readPod( _didImageSize );
	str.readPod( _nextDidDesc ); // TODO: Reslove to pointer via AObjDoc
	str.readPod( _didCompressMethod ); // seems to be a FOURCC
	str.readPod( _didResolutionId );
	str.readPod( _imageAlignmentFactor );
	
	readAndCheckExtHeader( str, 1, 69 );
	str.readPod( _frameIndexByteOrder );
	
	readAndCheckExtHeader( str, 2, 71 );
	str.readPod( _frameSampleSize );
	
	readAndCheckExtHeader( str, 3, 71 );
	str.readPod( _firstFrameOffset );
	
	readAndCheckExtHeader( str, 4, 71 );
	str.readPod( _clientFillStart );
	str.readPod( tagMark );
	TR_ASSERT( tagMark == 71 );
	str.readPod( _clientFillEnd );
	
	readAndCheckExtHeader( str, 5, 71 );
	str.readPod( _offsetToRleFrameIndexes );
	
	readAndCheckExtHeader( str, 8, 71 );
	str.readPod( _validXNum );       
	readTagMark( str, 71 );
	str.readPod( _validXDen );
	readTagMark( str, 71 );
	str.readPod( _validYNum );
	readTagMark( str, 71 );
	str.readPod( _validYDen );
	readTagMark( str, 71 );
	str.readPod( _validWidthNum );
	readTagMark( str, 71 );
	str.readPod( _validWidthDen );  
	readTagMark( str, 71 );
	str.readPod( _validHeighNum );
	readTagMark( str, 71 );  
	str.readPod( _validWidthDen ); 
	readTagMark( str, 71 );
	str.readPod( _essenceXNum );
	readTagMark( str, 71 );
	str.readPod( _essenceXDen ); 
    readTagMark( str, 71 );
	str.readPod( _essenceYNum );
	readTagMark( str, 71 );
	str.readPod( _essenceYDen );
	readTagMark( str, 71 );
	str.readPod( _essenceWidthNum ); 
	readTagMark( str, 71 );
	str.readPod( _essenceWidthDen );
	readTagMark( str, 71 );
	str.readPod( _essenceHeightNum );
	readTagMark( str, 71 );
	str.readPod( _essenceHeightDen );
	readTagMark( str, 71 );
	str.readPod( _sourceXNum );
	readTagMark( str, 71 );
	str.readPod( _sourceXDen );
	readTagMark( str, 71 );
	str.readPod( _sourceYNum );
	readTagMark( str, 71 );
	str.readPod( _sourceYDen );      
	readTagMark( str, 71 );
	str.readPod( _sourceWidthNum );
	readTagMark( str, 71 );
	str.readPod( _sourceWidthDen );
	readTagMark( str, 71 );
	str.readPod( _sourceHeightNum );
	readTagMark( str, 71 );
	str.readPod( _sourceHeighDen );  
}

#define TRACE_FIELD( x ) "\t" #x ": " << x << std::endl

void DIDDescriptor::dump( std::ostream& str ) const
{
	str << "DIDDescriptor {" << std::endl;
	
	str << "\t";
	AMediaFileDesc::dump( str );
	
	str << TRACE_FIELD( _storedHeight );
	str << TRACE_FIELD( _storedWidth );
	str << TRACE_FIELD( _sampledHeight );
	str << TRACE_FIELD( _sampledWidth );
	str << TRACE_FIELD( _sampledXOffset );
	str << TRACE_FIELD( _sampledYOffset );
	str << TRACE_FIELD( _displayHeight );
	str << TRACE_FIELD( _displayWidth );
	str << TRACE_FIELD( _displayXOffset );
	str << TRACE_FIELD( _displayYOffset );
	str << TRACE_FIELD( _frameLaout );
	str << "\t_imageAspectRatio: " << _imageAspectRatio;
	str << TRACE_FIELD( _videoLineMapSize );
	
	str << "\t_videoLineMap[ " << _videoLineMapSize / sizeof( Int32 ) << " ] {" << std::endl; 
	for( int i = 0; i < _videoLineMapSize / sizeof( Int32 ); ++i ) {
		str << "\t" << _videoLineMap[ i ] << std::endl;
	}
	str << "}" << std::endl;
	
	str << TRACE_FIELD( _alphaTransparency );
	str << TRACE_FIELD( _uniformness );
	str << TRACE_FIELD( _didImageSize );
	str << TRACE_FIELD( _nextDidDesc );
	str << "\t_didCompressMethod: " << _didCompressMethod << " ('" << pcidToString( _didCompressMethod ) << "')" << std::endl; // seems to be a fourcc
	str << TRACE_FIELD( _didResolutionId );
	str << TRACE_FIELD( _imageAlignmentFactor );
	
	str << TRACE_FIELD( _frameIndexByteOrder );
	str << TRACE_FIELD( _frameSampleSize );
	str << TRACE_FIELD( _firstFrameOffset );
	str << TRACE_FIELD( _clientFillStart );
	str << TRACE_FIELD( _clientFillEnd );
	str << TRACE_FIELD( _offsetToRleFrameIndexes );
	str << TRACE_FIELD( _validXNum );
	str << TRACE_FIELD( _validXDen );
	str << TRACE_FIELD( _validYNum );
	str << TRACE_FIELD( _validYDen );
	str << TRACE_FIELD( _validWidthNum );
	str << TRACE_FIELD( _validWidthDen );
	str << TRACE_FIELD( _validHeighNum );
	str << TRACE_FIELD( _validWidthDen );
	str << TRACE_FIELD( _essenceXNum );
	str << TRACE_FIELD( _essenceXDen );
	str << TRACE_FIELD( _essenceYNum );
	str << TRACE_FIELD( _essenceYDen );
	str << TRACE_FIELD( _essenceWidthNum );
	str << TRACE_FIELD( _essenceWidthDen );
	str << TRACE_FIELD( _essenceHeightNum );
	str << TRACE_FIELD( _essenceHeightDen );
	str << TRACE_FIELD( _sourceXNum );
	str << TRACE_FIELD( _sourceXDen );
	str << TRACE_FIELD( _sourceYNum );
	str << TRACE_FIELD( _sourceYDen );
	str << TRACE_FIELD( _sourceWidthNum );
	str << TRACE_FIELD( _sourceWidthDen );
	str << TRACE_FIELD( _sourceHeightNum );
	str << TRACE_FIELD( _sourceHeighDen );
	
	str << "}" << std::endl;
}